import os
import requests
from core.client import APIClient
from config.settings import Config
from lib.path_utils import PathUtils


class DownloadService:
    """下载服务，处理视频下载"""
    
    def __init__(self, client: APIClient):
        self.client = client
    
    def download_video(self, name: str, url: str, work_dir: str, m3u8_path: str):
        """根据URL类型选择合适的下载方式"""
        if url is None:
            print(f"视频 {name} 的URL为空，跳过下载")
            return
        
        if ".m3u8?" in url:
            self._download_m3u8(name, url, work_dir, m3u8_path)
        else:
            self._download_mp4(name, url, work_dir)
    
    def _download_m3u8(self, name: str, url: str, work_dir: str, m3u8_path: str):
        """使用第三方工具下载m3u8格式的视频"""
        # 使用路径工具确保路径正确
        work_dir = PathUtils.ensure_directory(work_dir)
        m3u8_path = PathUtils.get_executable_path(os.path.basename(m3u8_path))
        
        file_path = os.path.join(work_dir, f"{name}.mp4")
        
        # 检查文件是否已存在
        if os.path.exists(file_path):
            print(f"文件已存在: {name}，跳过下载。")
            return
        
        # 检查m3u8下载器是否存在
        if not os.path.exists(m3u8_path):
            print(f"错误：M3U8下载器未找到: {m3u8_path}")
            print("请确保 N_m3u8DL-CLI_v3.0.2.exe 存在于正确位置")
            return
        
        # 构建请求头字符串
        headers_str = self._build_headers_string()
        
        # 构建下载命令 - 使用路径工具处理路径
        # f'{M3U8_path} "{url}" --workDir "{workDir}" --saveName "{name}" --maxThreads "32" --retryCount "3" --headers "{headers_str}" --enableDelAfterDone '
        cmd = (
            f'{PathUtils.quote_path(m3u8_path)} "{url}" --workDir {PathUtils.quote_path(work_dir)} '
            f'--saveName "{name}" --maxThreads "{Config.DOWNLOAD_CONFIG["max_threads"]}" '
            f'--retryCount "{Config.DOWNLOAD_CONFIG["retry_count"]}" --headers "{headers_str}" '
            f'--enableDelAfterDone'
        )
        
        print(f"开始下载m3u8视频: {name}")
        print(f"执行命令: {cmd}")
        
        # 使用subprocess替代os.system以获得更好的错误处理
        import subprocess
        try:
            result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
            if result.returncode != 0:
                print(f"下载失败，错误信息: {result.stderr}")
        except Exception as e:
            print(f"执行命令时出错: {e}")
    
    def _download_mp4(self, file_name: str, url: str, work_dir: str):
        """使用requests下载MP4格式的视频"""
        # 使用路径工具确保目录存在
        work_dir = PathUtils.ensure_directory(work_dir)
        
        # 确保文件名以.mp4结尾
        if not file_name.endswith(".mp4"):
            file_name += ".mp4"
        
        # 处理文件名中的空格 - 创建子目录
        if " " in file_name:
            sub_dir = file_name.split(" ")[0]
            work_dir = PathUtils.ensure_directory(os.path.join(work_dir, sub_dir))
        
        full_path = os.path.join(work_dir, file_name)
        
        # 检查文件是否已存在
        existing_size = os.path.getsize(full_path) if os.path.exists(full_path) else 0
        
        try:
            # 获取文件大小
            head_response = requests.head(url, headers=self.client.headers)
            head_response.raise_for_status()
            total_size = int(head_response.headers.get('content-length', 0))
            
            if existing_size >= total_size > 0:
                print(f"文件已存在且完整，跳过下载：{full_path}")
                return
            
            # 设置断点续传
            headers = self.client.headers.copy()
            if existing_size > 0:
                headers["Range"] = f"bytes={existing_size}-"
            
            # 开始下载
            with requests.get(url, headers=headers, stream=True) as response:
                response.raise_for_status()
                
                mode = 'ab' if existing_size > 0 else 'wb'
                with open(full_path, mode) as file:
                    downloaded = existing_size
                    
                    for chunk in response.iter_content(chunk_size=Config.DOWNLOAD_CONFIG['chunk_size']):
                        if chunk:
                            file.write(chunk)
                            downloaded += len(chunk)
                            
                            # 显示进度
                            if total_size > 0:
                                progress = (downloaded / total_size) * 100
                                print(f"\r正在下载{file_name}: {downloaded}/{total_size} bytes ({progress:.2f}%)", end="")
                            else:
                                print(f"\r正在下载{file_name}: {downloaded} bytes", end="")
                
            print(f"\n下载完成：{full_path}")
            
        except requests.exceptions.RequestException as e:
            print(f"下载失败：{e}")
    
    def _build_headers_string(self) -> str:
        """构建请求头字符串用于m3u8下载器"""
        headers_str = ""
        for key, value in self.client.headers.items():
            headers_str += f"{key}:{value}|"
        return headers_str.strip("|")
    
    def cleanup_logs(self):
        """清理临时日志目录"""
        try:
            logs_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'tools', 'Logs')
            if os.path.exists(logs_dir):
                import shutil
                shutil.rmtree(logs_dir)
                print(f"已清理临时日志目录: {logs_dir}")
        except Exception as e:
            print(f"清理日志目录失败: {e}")
